from typing import Any, Dict, Optional, List
from utils.logger import Logger
from utils.constants import FallbackLevel, AGENT_TYPES
from auxiliary_agents.health_monitor import health_check_agent
from middleware.redis_adapter import get_redis_adapter
from config import base_config, agent_config

# 初始化日志
logger = Logger.get_logger(agent_name="fallback_manager")


class FallbackManager:
    """降级策略管理器（实现多层降级逻辑）"""

    def __init__(self):
        self.redis_client = get_redis_adapter()  # 使用Redis适配器，支持集群模式
        self.cache_prefix: str = "fallback:cache:"  # 降级缓存键前缀
        logger.info("降级策略管理器初始化完成")

    def _get_fallback_cache_key(self, task_id: str, agent_type: str) -> str:
        """生成降级缓存键"""
        return f"{self.cache_prefix}{agent_type}:{task_id}"

    def fallback_level1(self, agent_type: str) -> Optional[Dict[str, Any]]:
        """
        一级降级：同集群备用 Agent 实例
        从健康检查 Agent 获取当前负载最低的备用实例
        """
        try:
            # 获取该类型的健康 Agent 实例（已按负载排序）
            healthy_agents = health_check_agent.get_healthy_agents(agent_type)
            if healthy_agents:
                # 选择负载最低的实例
                fallback_agent = healthy_agents[0]
                logger.info(
                    f"一级降级：使用同集群备用实例: agent_type={agent_type}, agent_id={fallback_agent['agent_id']}")
                return fallback_agent
            logger.warning(f"一级降级失败：无健康的{agent_type}实例")
            return None
        except Exception as e:
            logger.error(f"一级降级异常: agent_type={agent_type}, error={str(e)}", exc_info=True)
            return None

    def fallback_level2(self, agent_type: str) -> Optional[Dict[str, Any]]:
        """
        二级降级：跨集群调度
        （实际场景需对接 Nacos 跨集群服务发现，此处简化为返回默认集群备用实例）
        """
        try:
            # 模拟跨集群获取实例（实际需扩展 Nacos 客户端的跨集群配置）
            cross_cluster_agent = {
                "agent_id": f"{agent_type}_cross_cluster_001",
                "service_url": f"http://{agent_type}-cross-cluster:8000",
                "status": "healthy",
                "task_count": 0
            }
            logger.info(f"二级降级：跨集群调度实例: agent_type={agent_type}, agent_id={cross_cluster_agent['agent_id']}")
            return cross_cluster_agent
        except Exception as e:
            logger.error(f"二级降级异常: agent_type={agent_type}, error={str(e)}", exc_info=True)
            return None

    def fallback_level3(self, task_id: str, agent_type: str) -> Optional[Any]:
        """
        三级降级：缓存兜底
        返回该任务/Agent 类型的历史缓存结果
        """
        try:
            cache_key = self._get_fallback_cache_key(task_id, agent_type)
            cached_result = self.redis_client.get(cache_key)
            if cached_result:
                logger.info(f"三级降级：使用缓存结果: task_id={task_id}, agent_type={agent_type}")
                return cached_result.decode("utf-8") if isinstance(cached_result, bytes) else cached_result
            logger.warning(f"三级降级失败：无缓存结果: task_id={task_id}, agent_type={agent_type}")
            return None
        except Exception as e:
            logger.error(f"三级降级异常: task_id={task_id}, agent_type={agent_type}, error={str(e)}", exc_info=True)
            return None

    def fallback_level4(self, agent_type: str) -> Dict[str, str]:
        """
        四级降级：友好提示
        返回预设的友好提示信息（最终兜底）
        """
        friendly_messages = {
            "text_qa_agent": "当前文本问答服务繁忙，请稍后重试~",
            "doc_qa_agent": "当前文档问答服务暂时不可用，建议您先尝试文本查询~",
            "multi_modal_agent": "当前多模态服务正在维护，预计10分钟后恢复~",
            "tool_call_agent": "当前工具调用服务暂时无法使用，请稍后再试~",
            "orchestrator_agent": "系统调度服务繁忙，请刷新页面后重试~"
        }
        message = friendly_messages.get(agent_type, "当前服务暂时不可用，请稍后重试~")
        logger.info(f"四级降级：返回友好提示: agent_type={agent_type}, message={message}")
        return {"code": -1, "message": message, "data": None}

    def execute_fallback(
            self,
            task_id: str,
            agent_type: str,
            current_level: int = 1,
            max_level: int = 4
    ) -> Any:
        """
        执行降级策略（从指定级别开始，直到找到可用降级方案）
        Args:
            task_id: 任务 ID
            agent_type: Agent 类型
            current_level: 起始降级级别（默认从一级开始）
            max_level: 最大降级级别（默认四级）
        Returns:
            降级后的结果/Agent 实例
        """
        if current_level > max_level:
            logger.error(f"所有降级级别均失败: task_id={task_id}, agent_type={agent_type}")
            return self.fallback_level4(agent_type)  # 最终兜底

        fallback_funcs = {
            1: self.fallback_level1,
            2: self.fallback_level2,
            3: lambda: self.fallback_level3(task_id, agent_type),
            4: lambda: self.fallback_level4(agent_type)
        }

        try:
            fallback_func = fallback_funcs.get(current_level)
            if not fallback_func:
                return self.execute_fallback(task_id, agent_type, current_level + 1, max_level)

            result = fallback_func() if current_level in [1, 2, 4] else fallback_func()
            if result is not None:
                return result
            # 当前级别失败，尝试下一级
            return self.execute_fallback(task_id, agent_type, current_level + 1, max_level)
        except Exception as e:
            logger.error(f"降级级别{current_level}执行异常: task_id={task_id}, agent_type={agent_type}, error={str(e)}")
            return self.execute_fallback(task_id, agent_type, current_level + 1, max_level)

    def cache_fallback_result(self, task_id: str, agent_type: str, result: Any, ttl: int = None) -> bool:
        """缓存降级结果（供后续降级使用）"""
        try:
            cache_key = self._get_fallback_cache_key(task_id, agent_type)
            ttl = ttl or base_config.cache_hot_key_ttl  # 默认使用热key缓存时长
            self.redis_client.set(key=cache_key, value=result, ex=ttl)
            logger.debug(f"缓存降级结果: task_id={task_id}, agent_type={agent_type}, ttl={ttl}s")
            return True
        except Exception as e:
            logger.error(f"缓存降级结果异常: task_id={task_id}, agent_type={agent_type}, error={str(e)}", exc_info=True)
            return False


# 单例实例（全局复用）
fallback_manager = FallbackManager()

# 测试入口
if __name__ == "__main__":
    test_logger = Logger.update_context(task_id="fallback_test")

    # 测试降级流程（模拟 text_qa_agent 所有实例故障）
    task_id = "test_task_001"
    agent_type = "text_qa_agent"

    # 缓存测试结果（供三级降级使用）
    fallback_manager.cache_fallback_result(task_id, agent_type, "缓存的问答结果：分布式多Agent系统很强大！")

    # 执行降级（从一级开始）
    fallback_result = fallback_manager.execute_fallback(task_id, agent_type)
    test_logger.info(f"最终降级结果: {fallback_result}")

    # 测试四级降级（模拟所有级别失败）
    fallback_result = fallback_manager.execute_fallback("test_task_002", "multi_modal_agent", current_level=4)
    test_logger.info(f"四级降级结果: {fallback_result}")